﻿using System.Linq;
using ACC.Data.Line;
using System.Collections.Generic;
using System;
using ACC.Data.Comm;
using System.Threading;
using ACC.Util.Log;
using ACC.Data;
using System.Data;
using ACC.Util.Common;
using System.Text;
using ACC.Data.Entities.Common;

namespace ACC.Device.Common
{
    public class ClientCommonDevice : ACCDevice
    {
        protected Entity _ClientCfg = null;
        public ClientCommonDriver _TerminalDriver;
        public static Int32 SLEEP_INTERVAL = 1000;

        public DictionaryEx<string, object> Variables = new DictionaryEx<string, object>();

        public ClientCommonDevice(StnRunningData stnData, ACCDriver driver)
            : base(stnData, driver)
        {
            _TerminalDriver = (ClientCommonDriver)driver;
        }

        protected override void Init()
        {
            base.Init();
        }

        public override void Start()
        {
            base.Start();

            if (_TerminalDriver != null)
            {
                _TerminalDriver.Connect();

                _TerminalDriver.OnSendClientConfig += OnSendClientConfig;
            }
        }

        public override void Stop()
        {
            base.Stop();

            Variables.Clear();
            if (_TerminalDriver != null)
            {
                try
                {
                    _TerminalDriver.Disconnect();
                }
                catch
                { }
                _TerminalDriver.OnSendClientConfig -= OnSendClientConfig;
            }
        }

        #region Client config
        void OnSendClientConfig()
        {
            try
            {
                LoadClientConfig();
            }
            catch (Exception ex)
            {
                logger.Error("Load terminal config failed:\n" + ex.StackTrace);
            }

            SendClientConfig(_ClientCfg);
        }

        public virtual int SendClientConfig(Entity ternimalCfg)
        {
            if (ternimalCfg == null)
            {
                return -1;
            }

            return _TerminalDriver.SendAccCmd(ACCCmd.ClientConfig, ternimalCfg);
        }

        public virtual void LoadClientConfig()
        {
            _ClientCfg = new TerminalConfig();

            (_ClientCfg as TerminalConfig).Line = _stnData.StnCfg.LineCfg.Line;
            (_ClientCfg as TerminalConfig).OP = _stnData.StnCfg.OPCfg.OP;
            (_ClientCfg as TerminalConfig).STN = _stnData.StnCfg.Name;

            string[] param = _stnData.StnCfg.Device == null ? null : _stnData.StnCfg.Device.Param.Split(';');
            if (param != null && param.Length > 2)
                (_ClientCfg as TerminalConfig).ServerIP = param[2];
            if (param != null && param.Length > 3)
                (_ClientCfg as TerminalConfig).ServerPort = int.Parse(param[3]);

            (_ClientCfg as TerminalConfig).Name = _stnData.StnCfg.Device == null ? "" : _stnData.StnCfg.Device.Name;
        }
        #endregion

        #region Module change
        public uint LastPartTypeId = 0;
        public ACCDevice.PartTypeDataResult LastPartTypeDataResult;
        public override ACCCode ReadParttypeDataParam(out uint PartTypeId)
        {
            PartTypeId = LastPartTypeId;

            return ACCCode.ACCOK;
        }

        public override ACCCode SendPartTypeData(ACCDevice.PartTypeDataResult result)
        {
            LastPartTypeDataResult = result;
            return ACCCode.ACCOK;
        }

        //public override void ChangePartNo(RuningPartNo oldpartno, RuningPartNo newpartno)
        //{
        //    ClientPartType partType = new ClientPartType()
        //            {
        //                PartTypeId = newpartno == null ? 0 : (int)newpartno.BomCfg.PartTypeID,
        //                Sequence = newpartno == null ? 0 : (int)newpartno.BomCfg.Sequence,
        //                PartNo = newpartno == null ? "" : newpartno.BomCfg.PartNo,
        //                Description = newpartno == null ? "" : newpartno.BomCfg.Desc
        //            };
        //    _TerminalDriver.SendAccCmd(ACCCmd.ClientModelChange, partType);

        //    base.ChangePartNo(oldpartno, newpartno);
        //}
        #endregion

        #region Load
        public ACCDevice.LoadParam LastLoadParam;
        public ACCDevice.LoadResult LastLoadResult;

        public override ACCCode ReadLoadParam(out ACCDevice.LoadParam loadParam)
        {
            loadParam = LastLoadParam;

            return loadParam == null ? ACCCode.ACCInternalError : ACCCode.ACCOK;
        }

        public override ACCCode SendLoadResult(ACCDevice.LoadResult result)
        {
            LastLoadResult = result;
            return ACCCode.ACCOK;
        }
        #endregion

        #region Unload
        public ACCDevice.UnloadParam LastUnloadParam;
        public ACCDevice.UnloadResult LastUnloadResult;

        public override ACCCode ReadUnloadParam(out ACCDevice.UnloadParam unloadParam)
        {
            unloadParam = LastUnloadParam;

            return unloadParam == null ? ACCCode.ACCInternalError : ACCCode.ACCOK;
        }

        public override ACCCode SendUnloadResult(ACCDevice.UnloadResult result)
        {
            LastUnloadResult = result;
            return ACCCode.ACCOK;
        }
        #endregion

        #region NextStep (PreLoad)
        public ACCDevice.NextStepParam LastNextStepParam;
        public ACCDevice.NextStepResult LastNextStepResult;

        public override ACCCode ReadNextStepParam(out ACCDevice.NextStepParam param)
        {
            param = LastNextStepParam;

            return param == null ? ACCCode.ACCInternalError : ACCCode.ACCOK;
        }

        public override ACCCode SendNextStepResult(ACCDevice.NextStepResult result)
        {
            LastNextStepResult = result;
            return ACCCode.ACCOK;
        }
        #endregion

        #region Print
        public ACCDevice.PrintResult LastPrintResult;
        public override ACCCode SendPrintResult(ACCDevice.PrintResult result)
        {
            LastPrintResult = result;
            return ACCCode.ACCOK;
        }
        #endregion

        #region Login
        public DictionaryEx<string, string> ClientLastOperatorId = new DictionaryEx<string, string>();
        public DictionaryEx<string, ClientOperator> ClientLastOperator = new DictionaryEx<string, ClientOperator>();

        public virtual ACCCode ReadLoginParam(ACCDevice dev, out string oprid)
        {
            oprid = ClientLastOperatorId[_stnData.StnCfg.Name];

            return ACCCode.ACCOK;
        }

        public virtual ACCCode ReadLogoutParam(ACCDevice dev, out string oprid)
        {
            oprid = ClientLastOperatorId[_stnData.StnCfg.Name];

            return ACCCode.ACCOK;
        }

        public virtual ACCCode SendLoginResult(string oprid)
        {
            ClientOperator opr = ClientLastOperator[oprid];
            if (opr == null || _TerminalDriver.SendAccCmd(ACCCmd.ClientLogin, opr) < 0)
                return ACCCode.ACCInternalError;

            return ACCCode.ACCOK;
        }

        public virtual ACCCode SendLogoutResult(string oprid)
        {
            ClientOperator opr = ClientLastOperator[oprid];
            if (_TerminalDriver.SendAccCmd(ACCCmd.ClientLogout, opr) < 0)
                return ACCCode.ACCInternalError;

            return ACCCode.ACCOK;
        }
        #endregion

        #region Lot Change
        public List<ACCDevice.LotChangeData> LastLotChangeDatas = new List<LotChangeData>();
        public ACCDevice.LotChangeResult LastLotChangeResult;

        public override ACCCode ReadLotChangeData(out List<ACCDevice.LotChangeData> data)
        {
            data = LastLotChangeDatas;
            return ACCCode.ACCOK;
        }

        public override ACCCode SendLotChangeResult(ACCDevice.LotChangeResult result)
        {
            LastLotChangeResult = result;
            return ACCCode.ACCOK;
        }
        #endregion
    }
}
